package czh.cocoa.ui.impl;

import czh.cocoa.animation.CABasicAnimation;
import czh.cocoa.animation.CALayer;
import czh.cocoa.animation.CAMediaTimingFunction;
import czh.cocoa.foundation.NSMutableString;
import czh.cocoa.foundation.NSNumber;
import czh.cocoa.foundation.NSObject;
import czh.cocoa.foundation.NSRange;
import czh.cocoa.foundation.NSSelector;
import czh.cocoa.foundation.NSString;
import czh.cocoa.graphics.CGRect;
import czh.cocoa.graphics.CGSize;
import czh.cocoa.ui.UIColor;
import czh.cocoa.ui.UIEvent;
import czh.cocoa.ui.UIFont;
import czh.cocoa.ui.UIImage;
import czh.cocoa.ui.UIKeyInput;
import czh.cocoa.ui.UITouch;
import czh.cocoa.ui.UIView;

public class UITextField extends UIControl implements UIKeyInput {
	
	public final static int UITextBorderStyleNone = 0;
	public final static int UITextBorderStyleLine = 1;
	public final static int UITextBorderStyleBezel = 2;
	public final static int UITextBorderStyleRoundedRect = 3;
	
	public final static int UITextFieldViewModeNever = 0;
	public final static int UITextFieldViewModeWhileEditing = 1;
	public final static int UITextFieldViewModeUnlessEditing = 2;
	public final static int UITextFieldViewModeAlways = 3;
	
	private final static float INPUT_CURSOR_WIDTH = 5;
	private final static float CLEAR_BUTTON_SIZE = 38;
	
	private int mBorderStyle;
	
	private UIImageView mBackgroundView;
	
	private UILabel mLabel;
	
	private NSMutableString mText;
	
	private UIView mCursorView;
	
	private int mClearButtonMode;
	
	private UIButton mClearButton;
	
	private boolean mSecureTextEntry;
	
	private int mKeyboardType;
	
	private NSString mPlaceholder;
	
	private UIColor mTextColor;
	
	private boolean mClearsOnBeginEditing;
	
	private UITextFieldDelegate mDelegate;

	public UITextField() {
		
	}
	
	public UITextField(CGRect frame) {
		super(frame);
	}
	
	protected void init() {
		super.init();
		mText = new NSMutableString();
		mBorderStyle = UITextBorderStyleNone;
		mClearButtonMode = UITextFieldViewModeNever;
		mKeyboardType = UIKeyboardTypeDefault;
		
		UIView input_view = new UIView(CGRectMake(10, 0, -20, 0));
		input_view.setClipsToBounds(true); 
		input_view.setAutoresizingMask(UIViewAutoresizingFlexibleSize);
		addSubview(input_view);
		
		mLabel = new UILabel(CGRectMake(INPUT_CURSOR_WIDTH, 0, -INPUT_CURSOR_WIDTH*2, 0)); 
		mLabel.setFont(UIFont.systemFontOfSize(20)); 
		mLabel.setAutoresizingMask(UIViewAutoresizingFlexibleSize);
		input_view.addSubview(mLabel); 
		
		mCursorView = new UIView(CGRectMake(0, 15, INPUT_CURSOR_WIDTH, -30));
		mCursorView.setAutoresizingMask(UIViewAutoresizingFlexibleHeight);
		mCursorView.setBackgroundColor(new UIColor(45/255f, 90/255f, 240/255f, 1)); 
		input_view.addSubview(mCursorView);
	
		mCursorView.setHidden(true);
		
		mClearButton = new UIButton(CGRectMake(- 10 - CLEAR_BUTTON_SIZE, 
				- CLEAR_BUTTON_SIZE / 2, CLEAR_BUTTON_SIZE, CLEAR_BUTTON_SIZE)); 
		mClearButton.setAutoresizingMask(UIViewAutoresizingFlexibleLeftMargin | 
				  UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
		mClearButton.setImageForState(UIImage.imageNamed(NSTR("cocoa/textfield_clear_button")), UIControlStateNormal); 
		mClearButton.setImageForState(UIImage.imageNamed(NSTR("cocoa/textfield_clear_button_highlighted")), UIControlStateHighlighted); 
		
		mClearButton.addTargetActionForControlEvents(this, new NSSelector() {
			@Override
			public void perform(NSObject receiver, NSObject params) {
				setText(NSTR("")); 
				if (!isEditing()) { 
					becomeFirstResponder();
				}
			}
		}, UIControlEventTouchUpInside);
		
		addSubview(mClearButton);
		
		mClearButton.setHidden(true);
		
		mTextColor = UIColor.blackColor();
	}
	 
	private void setCursorAnimationVisible(boolean visible) {
		if (visible) { 
			if (mCursorView.isHidden()) { 
				mCursorView.setHidden(false);
				CABasicAnimation anim = new CABasicAnimation(CALayer.ANIM_OPACITY);
				anim.setFromValue(new NSNumber(1));
				anim.setToValue(new NSNumber(0));
				anim.setRepeatCount(HUGE_VALF);
				anim.setAutoreverses(true);
				anim.setDuration(0.5);
				anim.setTimingFunction(CAMediaTimingFunction.EaseIn);
				mCursorView.layer().addAnimationForKey(anim, null);
			}
		} else {
			if (!mCursorView.isHidden()) { 
				mCursorView.setHidden(true);
				mCursorView.layer().removeAllAnimations();
			}
		}
	}
	
	public void setText(NSString text) {
//		if (text == null) { 
//			text = new NSString();
//		}
		mText.setString(text);
		updateTextLabel();
	}
	
	public NSString text() {
		return new NSString(mText); 
	}
	
	private void updateTextLabel() {
		if (!hasText() && !isEditing()) {
			mLabel.setTextColor(UIColor.colorWithWhiteAlpha(0.7f, 1)); 
			mLabel.setText(mPlaceholder);
		} else {
			mLabel.setTextColor(mTextColor);
			if (mSecureTextEntry) { 
				NSMutableString password = new NSMutableString();
				for (int i = 0; i < mText.length(); i++) {
					password.appendString(NSTR("•")); 
				}
				mLabel.setText(password);
			} else {
				mLabel.setText(text()); 
			}
		}
		adjustInputViewBounds();
	}
	
	private void adjustInputViewBounds() {
		adjustClearButtonVisible();
		
		CGRect label_frame = mLabel.frame();
		UIView input_view = mLabel.superview();
		CGRect bounds = input_view.bounds();
		
		float max_width = bounds.size.width - INPUT_CURSOR_WIDTH * 2 - 
						         (mClearButton.isHidden() ? 0 : CLEAR_BUTTON_SIZE + 5);
		
		if (isEditing()) { 
			CGSize size = CGSizeMake(9999, label_frame.size.height);   //INT32_MAX
			label_frame.size.width = mLabel.sizeThatFits(size).width;
			float offset = label_frame.size.width - max_width;
			bounds.origin.x = Math.max(0, offset);
			
			CGRect cursor_frame = mCursorView.frame();
			cursor_frame.origin.x = label_frame.origin.x + label_frame.size.width;
			mCursorView.setFrame(cursor_frame);
			
		} else {
			label_frame.size.width = max_width;
			bounds.origin.x = 0;
	
		}
		
		mLabel.setFrame(label_frame);
		input_view.setBounds(bounds);
	}
	
	public void setFont(UIFont font) {
		mLabel.setFont(font);
	}
	
	public UIFont font() {
		return mLabel.font();
	}
	
	public void setBorderStyle(int style) {
		if (style != mBorderStyle) { 
			mBorderStyle = style;
			switch (style) { 
			case UITextBorderStyleLine:
			case UITextBorderStyleBezel:
				layer().setBorderWidth(2);
				if (mBackgroundView != null) { 
					mBackgroundView.removeFromSuperview();
					mBackgroundView = null;
				}
				break;
			case UITextBorderStyleRoundedRect:
				layer().setBorderWidth(0);
				UIImage background = UIImage.imageNamed(NSTR("cocoa/textfield_background"));
				setBackground(background);
				break;
			case UITextBorderStyleNone:
			default:
				layer().setBorderWidth(0);
				if (mBackgroundView != null) { 
					mBackgroundView.removeFromSuperview();
					mBackgroundView = null;
				}
				break;
			}
		}
	}
	
	public int borderStyle() {
		return mBorderStyle;
	}
	
	public void setBackground(UIImage image) {
		if (mBackgroundView == null) {
			initBackgroundView();
		}
		mBackgroundView.setImage(image);
	}
	
	private void initBackgroundView() {
		mBackgroundView = new UIImageView(bounds());
		mBackgroundView.setAutoresizingMask(UIViewAutoresizingFlexibleSize);
		mBackgroundView.setContentStretch(CGRectMake(0.5f, 0.5f, 0.1f, 0.1f));
		insertSubviewAtIndex(mBackgroundView, 0);
	}
	
	public boolean canBecomeFirstResponder() {
		return true;
	}
	
	public void endTrackingWithTouchWithEvent(UITouch touch, UIEvent event) {
		super.endTrackingWithTouchWithEvent(touch, event);
		if (!isEditing()) { 
			becomeFirstResponder();
		}
	}

	@Override
	public void insertText(NSString text) {
		
		//NSLog("insert text: #%s#", text);
		
		if (text.isEqual(NSTR("\n"))) { 
			if (mDelegate != null) {
				mDelegate.textFieldShouldReturn(this);
			}
			return;
		}
		boolean changed = true;
		if (mDelegate != null) { 
			NSRange range = NSMakeRange(mText.length(), 0);
			changed = mDelegate.textFieldShouldChangeCharactersInRangeReplacementString(this, range, text);
		}
		if (changed) {
			mText.appendString(text);
			updateTextLabel(); 
		}
	}

	@Override
	public void deleteBackward() {
		int length = mText.length();
		if (length > 0) {
			boolean changed = true;
			if (mDelegate != null) { 
				NSRange range = NSMakeRange(mText.length() - 1, 1);
				changed = mDelegate.textFieldShouldChangeCharactersInRangeReplacementString(this, range, NSTR(""));
			}
			if (changed) {
				mText.deleteCharactersInRange(NSMakeRange(length - 1, 1)); 
				updateTextLabel();
			}
		}
	}
	
	public boolean becomeFirstResponder() {
		boolean ret = super.becomeFirstResponder();
		if (ret) { 
			setCursorAnimationVisible(true);
			if (!hasText()) { 
				mLabel.setText(null);
				adjustInputViewBounds();
			} else if(mClearsOnBeginEditing) {
				setText(NSTR("")); 
			} else {
				adjustInputViewBounds();
			}
			if (mDelegate != null) {
				mDelegate.textFieldDidBeginEditing(this);
			}
		}
		return ret;
	}
	
	public boolean resignFirstResponder() {
		boolean ret = super.resignFirstResponder();
		if (ret) { 
			setCursorAnimationVisible(false);
			if (hasText()) { 
				adjustInputViewBounds();
			} else {
				updateTextLabel();
			}
			if (mDelegate != null) {
				mDelegate.textFieldDidEndEditing(this);
			}
		}
		return ret;
	}
	
	public boolean isEditing() {
		return isFirstResponder();
	}
	 
	public void setClearButtonMode(int mode) {
		if (mClearButtonMode != mode) {
			mClearButtonMode = mode;
			adjustInputViewBounds();
		}
	}
	
	private void adjustClearButtonVisible() {
		int mode = mClearButtonMode;
		
		switch (mode) { 
		case UITextFieldViewModeAlways:
			mClearButton.setHidden(!hasText());
			break;
		case UITextFieldViewModeWhileEditing:
			if (isEditing()) { 
				mClearButton.setHidden(!hasText());
			} else {
				mClearButton.setHidden(true);
			}
			break;
		case UITextFieldViewModeUnlessEditing:
			if (!isEditing()) { 
				mClearButton.setHidden(!hasText());
			} else {
				mClearButton.setHidden(true);
			}
			break;
		case UITextFieldViewModeNever:
		default:
			mClearButton.setHidden(true);
			break;
		}
	}
	
	public int clearButtonMode() {
		return mClearButtonMode;
	}

	@Override
	public boolean hasText() {
		return mText.length() > 0;
	}
	
	public void setSecureTextEntry(boolean secure) {
		if (mSecureTextEntry != secure) { 
			mSecureTextEntry = secure;
			updateTextLabel();
		}
	}
	
	public boolean isSecureTextEntry() {
		return mSecureTextEntry;
	}

	public void setKeyboardType(int type) {
		mKeyboardType = type;
	}
	
	@Override
	public int keyboardType() {
		return mKeyboardType; 
	}
	
	public void setTextColor(UIColor color) {
		mTextColor = color;
		if (hasText()) { 
			mLabel.setTextColor(color);
		}
	}
	
	public UIColor textColor() {
		return mTextColor;
	}
	
	public void setPlaceholder(NSString placeholder) {
		mPlaceholder = placeholder;
		if (!hasText()) {
			updateTextLabel();
		}
	}
	
	public NSString placeholder() {
		return mPlaceholder;
	}
	
	public void setClearsOnBeginEditing(boolean clear) {
		mClearsOnBeginEditing = clear;
	}
	
	public boolean isClearsOnBeginEditing() {
		return mClearsOnBeginEditing;
	}
	
	public void setDelegate(UITextFieldDelegate delegate) {
		mDelegate = delegate;
	}
	
	public UITextFieldDelegate delegate() {
		return mDelegate;
	}
	
}
